TypeScript+Node.jsでsourcemap対応を加えてエラーログ調査を行いやすくしたい
吉川@広島です。
Node.js+TypeScriptで書いたコードをバンドルしてデプロイした場合に、sourcemap設定することでログに出力されたエラーを追うのが容易になります。本記事ではその設定方法を紹介します。
環境
- node 16.13.2
- typescript 4.5.5
- esbuild 0.14.17
- source-map-support 0.5.21
- date-fns 2.28.0
サンプルを用意する
esbuildでバンドルを行うのでインストールします。あと、何でも良かったのですがライブラリをバンドルしたコードを吐きたいのでdate-fnsを導入して使うようにします。
npm i date-fns && npm i -D typescript esbuild
で、サンプルとしてこんなコードを書きます。
// index.ts import { format } from 'date-fns' console.log(format(new Date(), 'yyyy-MM-dd')) // 今日の日付を出力(特に意味はない) throw new Error('MY_ERROR') // エラーを投げる
大事なのは5行目のエラーを投げる記述です。esbuildでバンドルして実行してみましょう。
npx esbuild index.ts --bundle --platform=node --target=node14 --outfile=index.js && node index.js
するとこのようなエラー出力を得ます。
Error: MY_ERROR at Object.<anonymous> (/path/to/sourcemap-support-playground/index.js:12074:7)
index.js:12074:7
だと元のコードの位置を特定するのに手間取りそうですね。
--minify
オプションをつけたパターンも試してみます。
npx esbuild index.ts --bundle --minify --platform=node --target=node14 --outfile=index.js && node index.js
Error: MY_ERROR at Object.<anonymous> (/path/to/sourcemap-support-playground/index.js:1:177156)
index.js:1:177156
もちょっと困りますね。
[方法1]source-map-supportを導入
この出力はsourcemap出力を行って対応させることで改善できます。
まず、source-map-supportを導入します。
evanw/node-source-map-support: Adds source map support to node.js (for stack traces)
npm i -D source-map-support
+import 'source-map-support/register' import { format } from 'date-fns' console.log(format(new Date(), 'yyyy-MM-dd')) throw new Error('MY_ERROR')
そして、バンドルする際にsourcemapを出力するよう設定します。esbuildに --sourcemap
オプションを加えて実行します。
npx esbuild index.ts --bundle --sourcemap --platform=node --target=node14 --outfile=index.js && node index.js
/path/to/sourcemap-support-playground/index.ts:6 throw new Error('MY_ERROR')
元のTypeScriptのコードの通り、 index.ts:6
と出してくれていますね。これでエラーの際の調査がしやすくなりました。また、 --minify
付きでも同じ結果が得られました。
[追記][方法2] --enable-source-maps
社内より「--enable-source-mapsでもできるよ」と助言頂いたのでこちらの方法も追記します。
Node.js v12.12.0から使えるようになったenable-source-mapsオプションを加えることでsource-map-supportをインストールしなくてもsourcemap対応ができるようです。 node --enable-source-maps index.js
のように実行します。
最初のsource-map-supportをimportしていないコードのまま、
npx esbuild index.ts --bundle --sourcemap --platform=node --target=node14 --outfile=index.js && node --enable-source-maps index.js
を実行して
Error: MY_ERROR at Object.<anonymous> (/path/to/sourcemap-support-playground/index.ts:5:7)
の結果を得ることができました。
また、AWS Lambdaなど実行時のオプションを指定することが難しい環境では
NODE_OPTIONS=--enable-source-maps
のように環境変数NODE_OPTIONSの仕組みを利用して有効化することもできるようです。
手元では
npx esbuild index.ts --bundle --sourcemap --platform=node --target=node14 --outfile=index.js && NODE_OPTIONS=--enable-source-maps node index.js
と実行したところ、期待通りの結果 ( index.ts:5:7
の出力) を得られました。
どっちの方法が良いの?
Node v12.12.0未満の場合、--enable-source-mapがないので、source-map-supportをインストールして使うことになるでしょう。
Node v12.12.0以上なら、
- できるだけ公式の仕組みに寄せる
- 依存ライブラリは少ない方が良い
という観点から、--enable-source-mapを使う方が良いように思います。ただし、このオプションはNode.js v14.x未満ではexperimentalステータスだったため、その点も加味して判断するのが良さそうです。
参考になれば幸いです。